﻿
    using System;
    using System.Collections.Generic;
#if !SILVERLIGHT || SL5 || WP8
    using System.Threading.Tasks;
#endif

namespace DailyFx.UI
{
    /// <summary>
    ///		Manages UI- Coroutined Call(s) Execution.
    /// </summary>
	public static class CoroutineSystem
	{
        static readonly ILog Log = LogManager.GetLog( typeof(CoroutineSystem) );


        /// <summary>
        ///		Runs a coroutine tasks .
        /// </summary>
        public static void Call ( IEnumerator<ICommand> calls, WeakAction context = null,
										EventHandler<CommandEventArgs> callback = null ) 
		{
            Log.Info("Coroutine ui call(s).");

			var c = new MarshalCommand ( calls );
            IoC.Satisfy( c );

            if ( callback != null ) 
			{
                OnCompleted ( c, callback );
            }

            OnCompleted( c, Completed );
            c.Call ( context ?? new WeakAction() );
        }

#if !SILVERLIGHT || SL5 || WP8
        /// <summary>
        ///		Runss a task asynchronous.
        /// </summary>
        /// <returns>
		///		A task that represents the asynchronous coroutine.
		///	</returns>
        public static Task CallEx ( IEnumerator<ICommand> calls, WeakAction context = null )
		{
            var taskSource = new TaskCompletionSource<object>();

            Call ( calls, context, (s, e) => 
			{
                if (e.Error != null)
				{
                    taskSource.SetException(e.Error);
				}
                else if ( e.Cancelled )
				{
                    taskSource.SetCanceled();
				}
                else
				{
                    taskSource.SetResult(null);
				}
            });

            return taskSource.Task;
        }
#endif

		

        /// <summary>
        ///		Called upon completion of a task .
        /// </summary>
        public static event EventHandler<CommandEventArgs> Completed = (s, e) =>
		{
            if( e.Error != null ) 
			{
                Log.Error( e.Error );
            }
            else if(e.Cancelled)
			{
                Log.Info(" Task is cancelled.");
            }
            else 
			{
                Log.Info("Task's completed.");
            }
        };

		/// <summary>
		/// 
		/// </summary>
        static void OnCompleted ( ICommand call, EventHandler<CommandEventArgs> handler )
		{
            EventHandler<CommandEventArgs> onCompledted = null;
            onCompledted = (s, e) => 
			{
                call.Completed -= onCompledted;
                handler(s, e);
            };
            call.Completed += onCompledted;
        }

    }

}
